package com.authine.cloudpivot.ext.controller;

import java.net.URLDecoder;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.xxpt.gateway.shared.api.request.OapiRpcOauth2DingtalkAppUserJsonRequest;
import com.alibaba.xxpt.gateway.shared.api.response.OapiRpcOauth2DingtalkAppUserJsonResponse;
import com.alibaba.xxpt.gateway.shared.client.http.ExecutableClient;
import com.alibaba.xxpt.gateway.shared.client.http.GetClient;
import com.alibaba.xxpt.gateway.shared.client.http.IntelligentPostClient;
import com.authine.cloudpivot.engine.api.model.organization.UserModel;
import com.authine.cloudpivot.web.api.controller.base.BaseController;
import com.authine.cloudpivot.web.sso.exception.UserException;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * Created by osfhmy on 2020/11/17.
 */
@Api(value = "单点登陆", tags = "01::EXTAPI::单点登陆")
@RestController
@RequestMapping("/api/sso")
@Slf4j
public class SsoLoginController extends BaseController {

    /**
     * accessKey
     */
    @Value("${syncorg.appKey}")
    private String appKey;

    /**
     * secretKey
     */
    @Value("${syncorg.appSecret}")
    private String appSecret;

    /**
     * domainName
     */
    @Value("${syncorg.domainName}")
    private String domainName;

    static final String dingtalkAppUserApi = "/rpc/oauth2/dingtalk_app_user.json";
    static final String tokenApi = "/gettoken.json";
    static String accessToken = "";
    // static final String accessKey = "choudpviot-80948K3yR5c303aE3qq";
    // static final String secretKey = "r1Jjd1D30a4PZop1428VNeJ25o4BwiA95zEOww76";
    // static final String domainName = "openplatform.dg-work.cn";

    /**
     * 校验地址
     */
    @Value("${project.sso.auth-url}")
    private String authUrl;

    /**
     * 请求工具
     */
    private static final RestTemplate restTemplate = new RestTemplate();

    /**
     * 如果不能访问到该路径，要把该路径添加到免校验里 src\main\java\com\authine\cloudpivot\web\api\config\ResourceConfig.java
     *
     * @param request
     * @param response
     * @param authCode
     *            专钉CODE
     * @return
     */
    @SuppressWarnings("static-access")
    @GetMapping("/app_user")
    @ApiOperation(value = "单点入口", notes = "xxx-SSO::单点入口")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "authCode", value = "专钉CODE", dataType = "string", paramType = "query")})
    public JSONObject root(HttpServletRequest request, HttpServletResponse response, String authCode) {
        log.info("入参authCode===== ... ... {}", authCode);
        accessToken = this.getAccessToken();
        ExecutableClient executableClient = ExecutableClient.getInstance();
        executableClient.setAccessKey(appKey);
        executableClient.setSecretKey(appSecret);
        executableClient.setDomainName(domainName);
        executableClient.setProtocal("https");
        executableClient.init();
        // executableClient保证单例
        IntelligentPostClient intelligentPostClient = executableClient.newIntelligentPostClient(dingtalkAppUserApi);
        OapiRpcOauth2DingtalkAppUserJsonRequest oapiRpcOauth2DingtalkAppUserJsonRequest =
            new OapiRpcOauth2DingtalkAppUserJsonRequest();
        // 登录access_token
        oapiRpcOauth2DingtalkAppUserJsonRequest.setAccess_token(accessToken);
        // 临时授权码
        oapiRpcOauth2DingtalkAppUserJsonRequest.setAuth_code(authCode);
        // 获取结果
        OapiRpcOauth2DingtalkAppUserJsonResponse apiResult =
            intelligentPostClient.post(oapiRpcOauth2DingtalkAppUserJsonRequest);
        log.info("获取到钉钉用户原始数据为===== ... ... {}", apiResult.toString());

        JSONObject parameter = new JSONObject().parseObject(apiResult.getContent());
        JSONObject returnData = new JSONObject();
        log.info("获取到钉钉用户信息为===== ... ... {}", parameter.toString());
        boolean success = parameter.getBooleanValue("success");
        String referId = "";
        if (success) {
            referId = parameter.getJSONObject("data").getString("referId");
        } else {
            returnData.put("Exception", new UserException("获取钉钉用户信息失败"));
            throw new UserException("获取钉钉用户信息失败");
        }
        log.info("开始统一认证referId=== ... ... {}", referId);
        if (referId.contains("_")) {
            referId = referId.substring(referId.indexOf("_") + 1);
            if (referId.contains("_")) {
                referId = referId.substring(0, referId.indexOf("_"));
            }
        }
        log.info("开始统一认证referId==== ... ... {}", referId);
        try {
            String url = authUrl.replaceAll("oauth", "") + "api/login/sso?code=" + referId;
            returnData = restTemplate.getForObject(url, JSONObject.class);
        } catch (Exception e) {
            log.error("Exception:{},{}", referId, JSONObject.toJSONString(e));
            e.printStackTrace();
            returnData.put("message", "处理跳转异常");
            returnData.put("Exception", JSONObject.toJSONString(e));
            return returnData;
        }
        return returnData;
    }

    /**
     * 跳转地址
     *
     * @param request
     * @param response
     * @param redirectUrl
     * @param js
     * @return
     * @throws Exception
     */
    @SuppressWarnings("unused")
    private boolean jumpToSSOUrl(HttpServletRequest request, HttpServletResponse response, String redirectUrl,
        JSONObject js) throws Exception {
        request.getSession().invalidate();
        redirectUrl = URLDecoder.decode(redirectUrl, "utf-8");

        StringBuilder url = new StringBuilder();
        if (!Objects.isNull(js)) {
            if (StringUtils.isNotEmpty(redirectUrl)) {
                if (redirectUrl.contains("admin")) {
                    url.append(authUrl.replaceAll("oauth", "/admin"));
                } else {
                    url.append(authUrl.replaceAll("oauth", ""));
                }
                url.append(redirectUrl);
                int index = url.indexOf("#");
                if (index > 0) {
                    url.replace(index - 1, index, "?access_token=" + js.get("access_token"));
                } else {
                    url.append("?access_token=").append(js.get("access_token"));
                }
            } else {
                url.append(authUrl.replaceAll("oauth", "")).append("?access_token=").append(js.get("access_token"));
            }
            log.info("登陆成功跳转到:{}", url);
            response.sendRedirect(url.toString());
        }
        return false;
    }

    @SuppressWarnings("static-access")
    public String getAccessToken() {
        ExecutableClient executableClient = ExecutableClient.getInstance();
        log.info("请求两KEY为=========={},{}", appKey, appSecret);
        executableClient.setAccessKey(appKey);
        executableClient.setSecretKey(appSecret);
        executableClient.setDomainName(domainName);
        executableClient.setProtocal("https");
        executableClient.init();
        // executableClient要单例，并且使用前要初始化，只需要初始化一次 61.141.65.29 15899963609_325334 Az168@2020
        // String api = getTokenApi;
        GetClient getClient = executableClient.newGetClient(tokenApi);
        getClient.addParameter("appkey", appKey);
        getClient.addParameter("appsecret", appSecret);
        String apiResult = getClient.get();
        JSONObject inParameter = new JSONObject().parseObject(apiResult);
        log.info("请求两KEY为=========={},{},获取返回参数===={}", appKey, appSecret, inParameter);
        String accessToken = inParameter.getJSONObject("content").getJSONObject("data").getString("accessToken");
        log.info("请求两KEY为=========={},{},得到accessToken===={}", appKey, appSecret, accessToken);
        return accessToken;
    }

    public UserModel getUser(String sourceId, String corpId) {
        // TODO 校验传入的参数信息，根据具体的场景匹配规则去查找用户
        UserModel userModel = null;
        userModel = this.getOrganizationFacade().getUserBySourceIdAndCorpId(sourceId, corpId);
        if (null == userModel) {
            log.error("单点登陆，在云枢中没有该用户的信息:{}", sourceId);
        } else {
            log.debug("单点登陆成功，用户的信息:{}->{}-{}", sourceId, userModel.getUsername(), userModel.getName());
        }
        return userModel;
    }
}
